//
//  MyDocument.m
//  CocOCaml
//
//	$Id: MyDocument.m,v 1.2 2003/02/27 17:35:32 wneuman Exp $
//
//  Created by William D. Neumann on Wed Feb 12 2003.
//  Copyright (c) 2003 William D. Neumann. All rights reserved.
//
//	This program is free software; you can redistribute it and/or modify
//	it under the terms of the Artistic License as published by Larry
//	Wall, either version 2.0, or (at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	Artistic License for more details.
//
//	You should have received a copy of the Artistic License with this Kit,
//	in the file named "Artistic.clarified".  If not, I'll be glad to provide
//	one.
//

#include <unistd.h>
#import "MyDocument.h"

@implementation MyDocument

- (id)init
{
    self = [super init];
    if (self) {
        rawHistoryData = nil;
        if ((currentEvents = [[History alloc] init]) == nil) {
            NSLog(@"Zaxxon!  [[History alloc] init] = %@",currentEvents);
            [self release];
            return nil;
        }

        toCamlFont = [[NSFont userFixedPitchFontOfSize:0.0] retain];
        toCamlColor = [[NSColor blueColor] retain];
        fromCamlFont = [[NSFont userFixedPitchFontOfSize:0.0] retain];
        fromCamlColor = [[NSColor darkGrayColor] retain];
        errorFromCamlFont = [[NSFont userFixedPitchFontOfSize:0.0] retain];
        errorFromCamlColor = [[NSColor redColor] retain];
    }
    return self;
}

- (NSString *)windowNibName
{
    // Override returning the nib file name of the document
    // If you need to use a subclass of NSWindowController or if your document
    // supports multiple NSWindowControllers, you should remove this method
    // and override -makeWindowControllers instead.
    return @"MyDocument";
}

- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
    [super windowControllerDidLoadNib:aController];

    //	Initialize and launch the interpreter
    interpreter = [[CamlController alloc] initWithOwner:self];

    [entryView setFont:toCamlFont];

    [historyView setTarget:self];
    [historyView setDoubleAction:@selector(tvDoubleClicked)];
    if (rawHistoryData)
    {
        clearToSend = NO;
        while (![interpreter taskIsRunning]) {}
        [self reliveHistory];
    } else
        clearToSend = YES;
}

- (NSData *)dataRepresentationOfType:(NSString *)aType
{
    HistoryElement * currentElement;
    NSEnumerator * historyEnumerator = [[currentEvents getChronological] objectEnumerator];
    NSString * historyRecord = @"";

    while (currentElement = [historyEnumerator nextObject]) {
        historyRecord = [historyRecord stringByAppendingFormat:@"%@\n\n",[currentElement getText]];
    }
    return [historyRecord dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
}

- (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType
{
    rawHistoryData = data;
    return rawHistoryData != nil;
}

- (IBAction)sortHistory:(id)sender
{
    [currentEvents toggleSort];
    if ([currentEvents isLexicographic])
        [sender setTitle:@"Sort Chronologically"];
    else
        [sender setTitle:@"Sort Lexicographically"];
    [historyView reloadData];
}

- (IBAction)submitCommand:(id)sender
{
    NSString* stringToSend = [NSString stringWithFormat:@"%@\n",[entryView string]];
    [self sendCommandToInterpreter:stringToSend];
}

- (void)sendCommandToInterpreter:(NSString *)theCommand
{
    HistoryElement* newElement;
    int camlViewLength,stsLength;

    camlViewLength = [[camlView textStorage] length];
    stsLength = [theCommand length];

    [camlView replaceCharactersInRange:NSMakeRange(camlViewLength,0)
                            withString:theCommand];
    [camlView setFont:toCamlFont
               range:NSMakeRange(camlViewLength,stsLength)];
    [camlView setTextColor:toCamlColor
                     range:NSMakeRange(camlViewLength,stsLength)];

    //  Add element to the history list
    newElement = [[HistoryElement alloc] initWithText:[entryView string]
                                             andIndex:([currentEvents count]+1)];
    [currentEvents addEvent:[newElement autorelease]];

    //	Send command to interpreter
    [interpreter sendDataToTask:[theCommand dataUsingEncoding:NSASCIIStringEncoding
                                           allowLossyConversion:YES]];
    clearToSend = NO;
    [entryView replaceCharactersInRange:NSMakeRange(0,[[entryView textStorage] length])
                             withString:@""];
    //	refresh history view
    [historyView reloadData];
    [historyView selectRow:([currentEvents count]-1) byExtendingSelection:NO];
    [historyView scrollRowToVisible:[currentEvents count]-1];
}

- (IBAction)previousHistory:(id)sender
{
    [self useCurrentHistoryItem:[currentEvents previousHistoryItem]];}

- (IBAction)nextHistory:(id)sender
{
    [self useCurrentHistoryItem:[currentEvents nextHistoryItem]];
}

- (IBAction)interruptInterpreter:(id)sender
{
    [interpreter interruptInterpreter];
}

- (void)useCurrentHistoryItem:(NSString *)theHistoryItem
{
    [entryView replaceCharactersInRange:NSMakeRange(0,[[entryView textStorage] length])
                             withString:theHistoryItem];
    // Scroll to bottom
    [entryView scrollRangeToVisible:NSMakeRange([[entryView textStorage] length], 0)];
    [historyView selectRow:[currentEvents getCurrentItem] byExtendingSelection:NO];
    [historyView scrollRowToVisible:[currentEvents getCurrentItem]];    
}

-(int) numberOfRowsInTableView:(NSTableView *)aTableView
{
    return [currentEvents count];
}

-(id) tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn
            row:(int)rowIndex
{
    HistoryElement* currentElement;
    NSString* identifier = [aTableColumn identifier];

    if ([currentEvents isLexicographic])
        currentElement = [[currentEvents getLexicographic] objectAtIndex:rowIndex];
    else
        currentElement = [[currentEvents getChronological] objectAtIndex:rowIndex];
    return [currentElement valueForKey:identifier];
}

-(void) updateCamlView:(NSString *)camlOutput
{
    int camlViewLength, outputLength;

    camlViewLength = [[camlView textStorage] length];
    outputLength = [camlOutput length];

    [camlView replaceCharactersInRange:NSMakeRange(camlViewLength,0)
                            withString:camlOutput];
    [camlView setFont:errorFromCamlFont
                range:NSMakeRange(camlViewLength,outputLength)];
    [camlView setTextColor:fromCamlColor
                     range:NSMakeRange(camlViewLength,outputLength)];
    
    camlViewLength += (outputLength + 1);
    [camlView scrollRangeToVisible:NSMakeRange(camlViewLength,0)];
    clearToSend = YES;
}

-(void) tvDoubleClicked
{
    int clickedRow = [historyView clickedRow];
    NSString* newEntryString;
    newEntryString =
        [[[historyView tableColumnWithIdentifier:@"getText"] dataCellForRow:clickedRow] stringValue];
    [entryView replaceCharactersInRange:NSMakeRange(0,[[entryView textStorage] length])
                             withString:newEntryString];
    [entryView scrollRangeToVisible:NSMakeRange([newEntryString length],0)];
    [entryView selectAll:self];
}

- (void) reliveHistory
{
    int i;
    //  Convert data to string and send to interpreter
    NSString * historyRecord = [[[NSString alloc] initWithData:rawHistoryData
                                                      encoding:NSASCIIStringEncoding] autorelease];

    NSArray * historyArray = [historyRecord componentsSeparatedByString:@"\n\n"];
    NSEnumerator * historyEnumerator = [historyArray objectEnumerator];
    NSString * currentString;

    while (currentString = [historyEnumerator nextObject]) {
        if ([currentString length] > 0) {
            [entryView replaceCharactersInRange:NSMakeRange(0,[[entryView textStorage] length])
                                     withString:currentString];
            [self sendCommandToInterpreter:[NSString stringWithFormat:@"%@\n",currentString]];
        }
    }
    for(i=0; i<[currentEvents count]; i++) {
    }
}

@end
